{/* Copyright 2020 Adobe. All rights reserved.
This file is licensed to you under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. You may obtain a copy
of the License at http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
OF ANY KIND, either express or implied. See the License for the specific language
governing permissions and limitations under the License. */}

import {Layout} from '@react-spectrum/docs';
export default Layout;

import docs from 'docs:@react-aria/checkbox';
import hiddenDocs from 'docs:@react-aria/visually-hidden';
import focusDocs from 'docs:@react-aria/focus';
import statelyDocs from 'docs:@react-stately/toggle';
import {HeaderInfo, FunctionAPI, TypeContext, InterfaceType, TypeLink, PageDescription} from '@react-spectrum/docs';
import {Keyboard} from '@react-spectrum/text';
import packageData from '@react-aria/checkbox/package.json';
import Anatomy from './checkbox-anatomy.svg';
import {ExampleCard} from '@react-spectrum/docs/src/ExampleCard';
import tailwindPreview from 'url:./tailwind-example.png';

---
category: Forms
keywords: [checkbox, input, aria]
---

# useCheckbox

<PageDescription>{docs.exports.useCheckbox.description}</PageDescription>

<HeaderInfo
  packageData={packageData}
  componentNames={['useCheckbox']}
  sourceData={[
    {type: 'W3C', url: 'https://www.w3.org/WAI/ARIA/apg/patterns/checkbox/'}
  ]} />

## API

<FunctionAPI function={docs.exports.useCheckbox} links={docs.links} />

## Features

Checkboxes can be built with the [&lt;input&gt;](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input)
HTML element, but this can be difficult to style. `useCheckbox` helps achieve accessible checkboxes
that can be styled as needed.

* Built with a native HTML `<input>` element, which can be optionally visually
  hidden to allow custom styling
* Full support for browser features like form autofill
* Keyboard focus management and cross browser normalization
* Labeling support for assistive technology
* Indeterminate state support

## Anatomy

<Anatomy />

A checkbox consists of a visual selection indicator and a label. Checkboxes support three
selection states: checked, unchecked, and indeterminate. Users may click or touch a checkbox
to toggle the selection state, or use the <Keyboard>Tab</Keyboard> key to navigate to it and the <Keyboard>Space</Keyboard> key to toggle it.

`useCheckbox` returns props to be spread onto its input element:

<TypeContext.Provider value={docs.links}>
  <InterfaceType properties={docs.links[docs.exports.useCheckbox.return.id].properties} />
</TypeContext.Provider>

Selection state is managed by the <TypeLink links={statelyDocs.links} type={statelyDocs.exports.useToggleState} />
hook in `@react-stately/toggle`. The state object should be passed as an option to `useCheckbox`.

In most cases, checkboxes should have a visual label. If the checkbox does not have a visible label,
an `aria-label` or `aria-labelledby` prop must be passed instead to identify the element to assistive
technology.

## Example

```tsx example
import {useCheckbox} from '@react-aria/checkbox';
import {useToggleState} from '@react-stately/toggle';

function Checkbox(props) {
  let {children} = props;
  let state = useToggleState(props);
  let ref = React.useRef(null);
  let {inputProps, labelProps} = useCheckbox(props, state, ref);

  return (
    <label {...labelProps} style={{display: 'block'}}>
      <input {...inputProps} ref={ref} />
      {children}
    </label>
  );
}

<Checkbox>Unsubscribe</Checkbox>
```

## Styling

To build a custom styled checkbox, you can make the native input element visually hidden.
This is possible using the &lt;<TypeLink links={hiddenDocs.links} type={hiddenDocs.exports.VisuallyHidden} />&gt;
utility component from `@react-aria/visually-hidden`. It is still in the DOM and accessible to
assistive technology, but invisible. This example uses SVG to build the visual checkbox,
which is hidden from screen readers with `aria-hidden`.

For keyboard accessibility, a focus ring is important to indicate which element has keyboard focus.
This is implemented with the <TypeLink links={focusDocs.links} type={focusDocs.exports.useFocusRing} />
hook from `@react-aria/focus`. When `isFocusVisible` is true, an extra SVG element is
rendered to indicate focus. The focus ring is only visible when the user is interacting
with a keyboard, not with a mouse or touch.

```tsx example export=true
import {VisuallyHidden} from '@react-aria/visually-hidden';
import {useFocusRing} from '@react-aria/focus';
import {mergeProps} from '@react-aria/utils';

function Checkbox(props) {
  let state = useToggleState(props);
  let ref = React.useRef(null);
  let {inputProps, labelProps} = useCheckbox(props, state, ref);
  let {isFocusVisible, focusProps} = useFocusRing();
  let isSelected = state.isSelected && !props.isIndeterminate;

  return (
    <label {...labelProps} style={{display: 'flex', alignItems: 'center', opacity: props.isDisabled ? 0.4 : 1}}>
      <VisuallyHidden>
        <input {...mergeProps(inputProps, focusProps)} ref={ref} />
      </VisuallyHidden>
      <svg
        width={24}
        height={24}
        aria-hidden="true"
        style={{marginRight: 4}}>
        <rect
          x={isSelected ? 4 : 5}
          y={isSelected ? 4 : 5}
          width={isSelected ? 16 : 14}
          height={isSelected ? 16 : 14}
          fill={isSelected ? 'orange' : 'none'}
          stroke={isSelected ? 'none' : 'gray'}
          strokeWidth={2}/>
        {isSelected &&
          <path
            transform="translate(7 7)"
            d={`M3.788 9A.999.999 0 0 1 3 8.615l-2.288-3a1 1 0 1 1
            1.576-1.23l1.5 1.991 3.924-4.991a1 1 0 1 1 1.576 1.23l-4.712
            6A.999.999 0 0 1 3.788 9z`} />
        }
        {props.isIndeterminate &&
          <rect x={7} y={11} width={10} height={2} fill="gray" />
        }
        {isFocusVisible &&
          <rect
            x={1}
            y={1}
            width={22}
            height={22}
            fill="none"
            stroke="orange"
            strokeWidth={2} />
        }
      </svg>
      {props.children}
    </label>
  );
}

<Checkbox>Unsubscribe</Checkbox>
```

## Styled examples

<ExampleCard
  url="https://codesandbox.io/s/bold-river-0v44z6?file=/src/Checkbox.tsx"
  preview={tailwindPreview}
  title="Tailwind CSS"
  description="An animated Checkbox built with Tailwind and React Aria." />

## Usage

The following examples show how to use the `Checkbox` component created in the above example.

### Default value

Checkboxes are not selected by default. The `defaultSelected` prop can be used to set the default state.

```tsx example
<Checkbox defaultSelected>Subscribe</Checkbox>
```

### Controlled value

The `isSelected` prop can be used to make the selected state controlled. The `onChange` event is fired when the user presses the checkbox, and receives the new value.

```tsx example
function Example() {
  let [selected, setSelection] = React.useState(false);

  return (
    <>
      <Checkbox isSelected={selected} onChange={setSelection}>
        Subscribe
      </Checkbox>
      <p>{`You are ${selected ? 'subscribed' : 'unsubscribed'}`}</p>
    </>
  );
 }
```

### Indeterminate

A Checkbox can be in an indeterminate state, controlled using the `isIndeterminate` prop.
This overrides the appearance of the Checkbox, whether selection is controlled or uncontrolled.
The Checkbox will visually remain indeterminate until the `isIndeterminate` prop is set to false, regardless of user interaction.

```tsx example
<Checkbox isIndeterminate>Subscribe</Checkbox>
```

### Disabled

Checkboxes can be disabled using the `isDisabled` prop.

```tsx example
<Checkbox isDisabled>Subscribe</Checkbox>
```

### Read only

The `isReadOnly` prop makes the selection immutable. Unlike `isDisabled`, the Checkbox remains focusable.
See the [MDN docs](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/readonly) for more information.

```tsx example
<Checkbox isSelected isReadOnly>Agree</Checkbox>
```


### HTML forms

Checkbox supports the `name` and `value` props for integration with HTML forms.

```tsx example
<Checkbox name="newsletter" value="subscribe">Subscribe</Checkbox>
```

## Internationalization

### RTL

In right-to-left languages, the checkbox should be mirrored. The checkbox should be placed on the right
side of the label. Ensure that your CSS accounts for this.
